#include <iostream>
using namespace std;
//template <typename R, typename T1, typename T2 >
//R func(T1 t1, T2 t2) //函数模板返回值必须显式定义，或者是利用auto关键字
//{
//    return t1 + t2;
//}

//包装器
//std::function
template <class R,class F, class T>
R useF(F f, T x)
{
    static int count = 0;
    cout << "count : " << ++count << endl;
    cout << "count : " << &count << endl;
    return f(x);
}

//函数指针
int func(int x)
{
    return static_cast<int>(x);
}
//函数对象
struct Functor
{
    int operator()(int x)
    {
        return static_cast<int>(x);
    }
};
//lambda表达式
auto f1 = [](int x)->int {return static_cast<int>(x);};

//std::bind
void testFunc(int a, int b, int c)
{
    cout << "values: " << a << " " << b << " " << c << endl;
}
//int main()
//{
    //std::function

    //测试一：
    //下面三次打印将函数模板useF实例化了3份,&count各不相同
    /*cout << useF<double>(func,3) << endl;
    cout << useF<double>(Functor(),13) << endl;
    cout << useF<double>(f1,32) << endl;*/

    //测试二：
    //只将函数模板useF实例化了1份，&count都相同
    //使用std::function包装函数func
    //function<double(int)> func1 = func;
    //cout << useF<double>(func1, 3) << endl;
    //包装匿名对象Functor()
    //function<double(int)> func2 = Functor();
    //cout << useF<double>(func2, 13) << endl;
    //包装lambda表达式
    //function<double(int)> func3 = f1;
    //cout << useF<double>(func3, 32) << endl;
    /*float a = 23;
    cout << a << endl;//cout << (float)a <<endl;
    printf("%f\n", a);*/
    //cout << "------------------------------" << endl;
    //std::bind
    //int t = 5;
    //auto boundFunc = std::bind(testFunc, std::placeholders::_2, 2, std::placeholders::_1);
    //boundFunc(t,6); //6 2 3
    //retuclass Test1
{
public:
	void print(int& a)
	{
		cout << "a=" << a << endl;
		++a;
	}
};

int main()
{
	int k = 0;
	int j = 1;
	function<void()> f = bind(&Test1::print, Test1(), std::ref(k));
	f();
	cout << k << endl;
	int* ptr = new int[3]{ 1,2,3 };
	int& a = *(ptr + 1);
	++a;
	cout << ptr[0] << " " << ptr[1] <<  endl;
	delete[] ptr;rn 0;
//}

